package com.zzyl.nursing.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.utils.PDFUtil;
import com.zzyl.common.utils.ThrowUtils;
import com.zzyl.nursing.constant.RedisKeyConstant;
import com.zzyl.nursing.domain.HealthAssessment;
import com.zzyl.nursing.dto.HealthAssessmentDto;
import com.zzyl.nursing.mapper.HealthAssessmentMapper;
import com.zzyl.nursing.service.IHealthAssessmentService;
import com.zzyl.nursing.utils.IDCardUtils;
import com.zzyl.nursing.vo.HealthReportVo;
import com.zzyl.oss.AliyunOSSOperator;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 健康评估Service业务层处理
 *
 * @author ruoyi
 * @date 2025-10-18
 */
@Service
@RequiredArgsConstructor
public class HealthAssessmentServiceImpl extends ServiceImpl<HealthAssessmentMapper, HealthAssessment> implements IHealthAssessmentService {
    private final HealthAssessmentMapper healthAssessmentMapper;
    private final AliyunOSSOperator aliyunOSSOperator;
    private final RedisTemplate<String, String> redisTemplate;
    private final ChatClient chatClient;
    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 查询健康评估
     *
     * @param id 健康评估主键
     * @return 健康评估
     */
    @Override
    public HealthAssessment selectHealthAssessmentById(Long id) {
        return getById(id);
    }

    /**
     * 查询健康评估列表
     *
     * @param healthAssessment 健康评估
     * @return 健康评估
     */
    @Override
    public List<HealthAssessment> selectHealthAssessmentList(HealthAssessment healthAssessment) {
        return healthAssessmentMapper.selectHealthAssessmentList(healthAssessment);
    }

    /**
     * 新增健康评估
     *
     * @param requestParam 健康评估
     * @return 结果
     */
    @Override
    public Long insertHealthAssessment(HealthAssessmentDto requestParam) {
        //数据分析
        //从redis获取老人的体检报告
        String pdfContent = redisTemplate.opsForValue().get(RedisKeyConstant.buildElderPdfKey(requestParam.getIdCard()));
        ThrowUtils.throwIf(StrUtil.isBlank(pdfContent), "没有对应的PDF文件内容" );
        String content = chatClient.prompt(pdfContent)
                .advisors(a -> a
                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, requestParam.getIdCard())
                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)
                ).call().content();
        //解析数据
        HealthReportVo report = JSONUtil.toBean(content, HealthReportVo.class);
        //保存数据
        return insertHealthReport(report, requestParam);

    }

    /**
     * 插入健康报告
     *
     * @param healthReportVo 健康报告
     * @return 插入结果
     */
    private Long insertHealthReport(HealthReportVo healthReportVo, HealthAssessmentDto healthAssessmentDto) {

        HealthAssessment healthAssessment = new HealthAssessment();
        // 总检日期
        healthAssessment.setTotalCheckDate(healthReportVo.getTotalCheckDate());
        healthAssessment.setElderName(healthAssessmentDto.getElderName());
        String idCard = healthAssessmentDto.getIdCard();
        healthAssessment.setIdCard(idCard);
        healthAssessment.setBirthDate(IDCardUtils.getBirthDateByIdCard(idCard));
        healthAssessment.setAge(IDCardUtils.getAgeByIdCard(idCard));
        healthAssessment.setGender(IDCardUtils.getGenderFromIdCard(idCard));
        double healthScore = healthReportVo.getHealthAssessment().getHealthIndex();
        healthAssessment.setHealthScore(String.valueOf(healthScore));
        healthAssessment.setRiskLevel(healthReportVo.getHealthAssessment().getRiskLevel());
        // 是否建议入住
        healthAssessment.setSuggestionForAdmission(getSuggestionForAdmission(healthScore));
        //护理等级
        healthAssessment.setNursingLevelName(getNursingLevelName(healthScore));
        healthAssessment.setAdmissionStatus(1);
        healthAssessment.setTotalCheckDate(healthReportVo.getTotalCheckDate());
        healthAssessment.setPhysicalExamInstitution(healthAssessmentDto.getPhysicalExamInstitution());
        healthAssessment.setPhysicalReportUrl(healthAssessmentDto.getPhysicalReportUrl());
        healthAssessment.setAssessmentTime(LocalDateTime.now());
        healthAssessment.setReportSummary(healthReportVo.getSummarize());
        //疾病风险
        healthAssessment.setDiseaseRisk(JSONUtil.toJsonStr(healthReportVo.getRiskDistribution()));
        //异常分析
        healthAssessment.setAbnormalAnalysis(JSONUtil.toJsonStr(healthReportVo.getAbnormalData()));
        //健康系统分值
        healthAssessment.setSystemScore(JSONUtil.toJsonStr(healthReportVo.getSystemScore()));
        save(healthAssessment);
        return healthAssessment.getId();
    }

    /**
     * 计算护理等级
     *
     * @param healthScore 健康分
     * @return 护理等级
     */
    private String getNursingLevelName(double healthScore) {
        // 处理边界
        if (healthScore < 0 || healthScore > 100) {
            throw new IllegalArgumentException("健康评分必须在0到100之间" );
        }

        if (healthScore >= 60 && healthScore < 70) {
            return "三级护理等级";
        } else if (healthScore >= 70 && healthScore < 80) {
            return "二级护理等级";
        } else if (healthScore >= 80 && healthScore < 90) {
            return "一级护理等级";
        } else if (healthScore >= 90) {
            return "特级护理等级";
        }
        return "无";

    }

    /**
     * 是否建议入住
     *
     * @param healthScore 健康分
     * @return 0:建议入住，1:不建议入住
     */
    private Integer getSuggestionForAdmission(double healthScore) {
        if (healthScore >= 60) {
            return 0;
        }
        return 1;

    }


    /**
     * 修改健康评估
     *
     * @param healthAssessment 健康评估
     * @return 结果
     */
    @Override
    public int updateHealthAssessment(HealthAssessment healthAssessment) {

        return updateById(healthAssessment) ? 1 : 0;
    }

    /**
     * 批量删除健康评估
     *
     * @param ids 需要删除的健康评估主键
     * @return 结果
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteHealthAssessmentByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除健康评估信息
     *
     * @param id 健康评估主键
     * @return 结果
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteHealthAssessmentById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    @SneakyThrows
    @Override
    public String uploadFile(MultipartFile file, String idCardNo) {
        String url = aliyunOSSOperator.upload(file.getBytes(), Objects.requireNonNull(file.getOriginalFilename()));
        // PDF文件内容读取为字符串
        String content = PDFUtil.pdfToString(file.getInputStream());
        //将老人提交报告临时存储到redis中，方便后续查询
        long expireSeconds = 60 + RandomUtil.randomInt(60);
        redisTemplate.opsForValue().set(RedisKeyConstant.buildElderPdfKey(idCardNo), Objects.requireNonNull(content)
                , expireSeconds, TimeUnit.DAYS);
        return url;
    }
}
